<template>
  <div class="container">
    <div class="nav">
      <el-button
        v-for="(item, index) in navList"
        :key="index"
        :type="item.type"
        @click="clickEvt(item.event)"
        >{{ item.text }}
      </el-button>
    </div>
    <div class="map" id="map"></div>
    <div class="pop" ref="pop">
      <div class="pop-title">
        <div class="close" @click="closePop()">
          <el-icon><Close /></el-icon>
        </div>
      </div>
      <div class="pop-content">
        <div class="cell">
          <div class="cell-name">地址：</div>
          <div class="cell-value">{{ targetInfo?.name }}</div>
        </div>
        <div class="cell">
          <div class="cell-name">坐标：</div>
          <div class="cell-value">
            {{ targetInfo?.lng }},{{ targetInfo?.lat }}
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted } from "vue";
import { useRouter } from "vue-router";

import "ol/ol.css";
import { Feature, Map, Overlay, View } from "ol";
import TileLayer from "ol/layer/Tile";
import ImageLayer from "ol/layer/Image";
import { ImageWMS, TileWMS, XYZ } from "ol/source";
import VectorSource from "ol/source/Vector";
import VectorLayer from "ol/layer/Vector";
import GeoJson from "ol/format/GeoJSON";
import { Style, Fill, Stroke, Text, Icon } from "ol/style";
import { fromLonLat } from "ol/proj";

import sichuanJson from "@/assets/json/sichuan.json";
import ic_point from "@/assets/img/map/ic_point.png";
import { Point, LineString } from "ol/geom";

import routeData from "./json/routeData.json";

type PointType = {
  lng: string;
  lat: string;
  name: string;
};

const router = useRouter();
let map: Map;
let sichuanLayer: VectorLayer; //四川地图实例
let popOverlay: any;
let tian_di_tu_img_c: any; //天地图卫星底图
let tian_di_tu_text: any; //天地图文字和交通底图
let WMSLayer: any;
const mapCenter = [106.372579, 29.766785]; //设置地图中心点
/*将默认WGS的坐标:EPSG:4326 转化为墨卡托类型(地球两极出现拉伸):EPSG:3857
如果想将墨卡托坐标转为经纬度坐标 请使用 toLonLat()
transform([120.001,30.212],'EPSG:转换前的目标','EPSG:转化后的目标')
*/
let routeLayer: any; //轨迹路线的实例
const features = ref<any>([]); //用于存放点位的信息

const pop = ref<HTMLDivElement | undefined>(undefined); //弹窗实例
const targetInfo = ref<PointType>();

const navList = [
  {
    text: "四川地图",
    type: "",
    event: "showJson",
  },
  {
    text: "添加点位",
    type: "",
    event: "showPoint",
  },
  {
    text: "保留四川地图",
    type: "",
    event: "showSichuan",
  },
  // {
  //   text: "轨迹路线",
  //   type: "",
  //   event: "showRoute",
  // },
  {
    text: "添加WMS服务",
    type: "",
    event: "showWMS",
  },
  {
    text: "重置地图",
    type: "",
    event: "reset",
  },
  {
    text: "返回后台",
    type: "primary",
    event: "return",
  },
];
const pointList: PointType[] = [
  {
    lng: "104.065735",
    lat: "30.659462",
    name: "成都市",
  },
  {
    lng: "104.773447",
    lat: " 29.352765",
    name: "自贡市",
  },
];

//nav的点击事件
function clickEvt(e: string) {
  const view = map.getView();
  if (e === "return") {
    router.push("/home");
  } else if (e === "showJson") {
    addGeoJson();
    view.animate({ zoom: 7, center: mapCenter });
  } else if (e === "reset") {
    reset();
    view.animate({ zoom: 5, center: mapCenter });
  } else if (e === "showPoint") {
    showPoint();
    view.animate({ zoom: 7, center: mapCenter });
  } else if (e === "showWMS") {
    showWMS();
    view.animate({ zoom: 17, center: mapCenter });
  } else if (e === "showSichuan") {
    showSichuan();
  } else if (e === "showRoute") {
    showRoute();
  }
}
//加载轨迹路线
function showRoute() {
  console.log("绘制轨迹路线图");
  let lineData = [
    [106.37468989849472, 29.767780099544538],
    [106.3699745750465, 29.767165873680117],
  ];
  let feature = new Feature({
    geometry: new LineString(lineData),
  });
  const lineStyle = new Style({
    stroke: new Stroke({
      color: "red",
      width: 10,
    }),
  });
  feature.setStyle(lineStyle);
  const lineSource = new VectorSource({ wrapX: false });
  routeLayer = new VectorLayer({
    source: lineSource,
  });
  console.log("routeLayer==", routeLayer);

  map.addLayer(routeLayer);
  //   map.addLayer(routeLayer);
  // let routeCom = [];
  // let routeFeature: any;
  // routeData.forEach((item: number[]) => {
  //   routeCom.push(item);
  //   routeFeature = new Feature({
  //     geometry: new LineString(routeCom),
  //   });
  //   routeFeature.setStyle(
  //     new Style({
  //       stroke: new Stroke({
  //         // 设置边的样式
  //         color: "rgb(21, 106, 158)",
  //         width: 3,
  //       }),
  //     })
  //   );
  //   const lineSoure = new VectorSource({ wrapX: false });
  //   lineSoure.addFeature(routeFeature);
  //   routeLayer = new VectorLayer({
  //     source: lineSoure,
  //   });
  //   map.addLayer(routeLayer);
  // routeLayer.getSource().addFeatures([routeFeature]);
  // });
}
//隐藏其他图层
function showSichuan() {
  const view = map.getView();
  //隐藏底图
  tian_di_tu_img_c.setVisible(false);
  tian_di_tu_text.setVisible(false);
  //加载四川地图
  addGeoJson();
  view.animate({ zoom: 7, center: mapCenter });
}
//加载WMS服务
function showWMS() {
  if (WMSLayer) {
    map.removeLayer(WMSLayer);
  }
  WMSLayer = new ImageLayer({
    // preload: Infinity,
    source: new ImageWMS({
      //不能设置为0，否则地图不展示。
      ratio: 1,
      url: "https://cdjinyatu.com/geoserver/cite/wms",
      params: {
        SERVICE: "WMS",
        REQUEST: "GetMap",
        LAYERS: "cite:001",
        STYLES: "",
        VERSION: "1.1.0",
        FORMAT: "image/png",
      },
      serverType: "geoserver",
    }),
  });
  map.addLayer(WMSLayer);
}
//初始化地图
function reset() {
  if (sichuanLayer) {
    map.removeLayer(sichuanLayer);
  }
  if (features.value.length > 0) {
    features.value.forEach((feature: any) => {
      feature.setStyle(new Style({})); //设置为空时，进行隐藏
    });
  }
  if (WMSLayer) {
    map.removeLayer(WMSLayer);
  }
  tian_di_tu_img_c.setVisible(true);
  tian_di_tu_text.setVisible(true);
}
//显示点位
function showPoint() {
  features.value.forEach((feature: any) => {
    const targetData = feature.getProperties();
    const styleObj = createStyle(targetData.data);
    feature.setStyle(styleObj);
  });
}
//统一给节点添加样式
function createStyle(data: PointType) {
  const styleObj = new Style({
    image: new Icon({
      src: ic_point,
      scale: 0.2,
    }),
    text: new Text({
      text: data.name,
      font: "normal 12px 微软雅黑", //字体样式
      scale: 1,
      fill: new Fill({
        //文字填充样式
        color: "orange",
      }),
      offsetY: 30,
      padding: [3, 2, 1, 2],
    }),
  });
  return styleObj;
}
//地图上添加点位
function addPoint() {
  //批量添加点位进数组
  pointList.forEach((item: PointType) => {
    const point = new Feature({
      data: item,
      type: "point", //自定义数据，用于区分点坐标
      geometry: new Point([Number(item.lng), Number(item.lat)]),
    });
    point.setStyle(new Style({})); //初始赋值为空
    features.value.push(point);
  });
  const source = new VectorSource({
    features: features.value,
  });

  const sourceLayer = new VectorLayer();
  sourceLayer.setSource(source);
  sourceLayer.setZIndex(2); //层级越大的 放置在最上面
  map.addLayer(sourceLayer);
}
//返回默认样式
function getDefaultStyle(feature: any) {
  const styleObj = new Style({
    fill: new Fill({
      color: "rgba(0,0,0,0.7)",
    }),
    //边界线
    stroke: new Stroke({
      color: "#fff",
      width: 2,
    }),
  });
  return styleObj;
}
//高亮地块
let highlightLayer: any = null;
//返回高亮样式
function getHighLightStyle(feature: any) {
  const cityName = feature.get("name");
  const styleObj = new Style({
    fill: new Fill({
      color: "rgba(100,100,100,0.5)",
    }),
    //边界线
    stroke: new Stroke({
      color: "#fff",
      width: 2,
    }),
    text: new Text({
      font: "12px Calibri,sans-serif", // 字体样式
      text: cityName, // 显示的市级名称
      fill: new Fill({
        color: "#fff", // 字体颜色
      }),
      stroke: new Stroke({
        color: "#000", // 字体边界颜色
        width: 3, // 字体边界宽度
      }),
    }),
  });
  return styleObj;
}
//加载geojson图层
function addGeoJson() {
  //避免异常，有地图需要先清空
  if (sichuanLayer) {
    map.removeLayer(sichuanLayer);
  }
  const geoJsonLayer = new VectorSource({
    features: new GeoJson().readFeatures(sichuanJson), //加载本地的json文件  注意是features 不要少写s
  });
  sichuanLayer = new VectorLayer({
    source: geoJsonLayer,
    style: getDefaultStyle,
    visible: true,
  });
  sichuanLayer.setZIndex(1);
  map.addLayer(sichuanLayer);
}
//加载弹窗
function addOverlay() {
  if (pop.value) {
    popOverlay = new Overlay({
      element: pop.value,
      autoPan: true,
    });
    popOverlay.setPosition(undefined); //undefined 不显示
    map.addOverlay(popOverlay);
  }
}
//关闭弹窗
function closePop() {
  popOverlay.setPosition(undefined);
}
//初始化地图
function initMap() {
  tian_di_tu_img_c = new TileLayer({
    source: new XYZ({
      url: "http://t0.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=224607697c91b31017453904fee47ded",
    }),
    visible: true,
  });
  tian_di_tu_text = new TileLayer({
    source: new XYZ({
      url: "http://t0.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=224607697c91b31017453904fee47ded",
    }),
    visible: true,
  });

  map = new Map({
    target: "map",
    layers: [tian_di_tu_img_c, tian_di_tu_text],
    view: new View({
      center: mapCenter,
      zoom: 5,
      maxZoom: 18, //矢量图官方给的层级为[0-18]，图层使用更高清的 可以设置为24
      projection: "EPSG:4326", //指定为EPSG:4326类型的经纬度，否则center需要进行ol.proj.transform 的转化
      // constrainResolution: true, //缩放层级为整数
      // smoothResolutionConstraint: false, //关闭无极缩放
    }),
  });
  addPoint(); //添加点位信息
  addOverlay(); //添加弹窗信息
  //地图单击事件
  map.on("singleclick", (e) => {
    const feature = map.forEachFeatureAtPixel(e.pixel, function (feature) {
      return feature;
    });
    if (!feature) {
      return;
    }

    const targetData = feature.getProperties(); //获取点击到的feature
    if (targetData.type == "point") {
      popOverlay.setPosition(e.coordinate);
      targetInfo.value = targetData.data;
    } else {
      popOverlay.setPosition(undefined);
    }
  });

  //鼠标移入事件
  map.on("pointermove", (e) => {
    //给移入的区块添加高亮
    const feature = map.forEachFeatureAtPixel(e.pixel, function (feature) {
      return feature;
    });

    if (feature && feature !== highlightLayer) {
      const targetData = feature.getProperties();
      //如果移入的是点位 就停止
      if (targetData.type == "point") {
        return;
      }
      if (highlightLayer) {
        highlightLayer.setStyle(getDefaultStyle);
      }
      // 设置当前要素为高亮样式
      highlightLayer = feature;
      highlightLayer.setStyle(getHighLightStyle);
      map.getTargetElement().style.cursor = "pointer";
    } else if (!feature && highlightLayer) {
      highlightLayer.setStyle(getDefaultStyle);
      highlightLayer = null;
    }
  });
}
onMounted(() => {
  initMap();
});
</script>

<style lang="scss" scoped>
.container {
  width: 100%;
  height: 100%;
  position: relative;
  .nav {
    width: 100%;
    height: 50px;
    display: flex;
    justify-content: space-around;
    align-items: center;
  }
  .map {
    width: 100%;
    height: calc(100% - 30px);
  }
  .pop {
    position: absolute;
    background-color: white;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
    padding: 15px;
    border-radius: 10px;
    border: 1px solid #cccccc;
    bottom: 12px;
    left: -50px;
    min-width: 200px;
    .pop-title {
      height: 1rem;
      width: 100%;
      display: flex;
      justify-content: flex-end;

      .close {
        width: 1rem;
        height: 1rem;
        cursor: pointer;
      }
    }
    .cell {
      display: flex;
      justify-content: space-between;
      .cell-name {
        width: 3rem;
        text-align: justify;
      }
      .cell-name::after {
        content: "";
        display: inline-block;
        width: 100%;
      }
      .cell-value {
        flex: 1;
      }
    }
  }
}
</style>